xtensa: build: add support for build with upstream llvm clang with binutils backend#108765
Draft
lgirdwood wants to merge 47 commits into
Draft
xtensa: build: add support for build with upstream llvm clang with binutils backend#108765lgirdwood wants to merge 47 commits into
lgirdwood wants to merge 47 commits into
Conversation
Author
|
SOF PR for anyone interested: thesofproject/sof#10759 |
|
Author
|
@cgturner1 @dcpleung fyi - now builds working SOF for multiple platforms using single compiler but still uses SDK binutils today. |
lgirdwood
force-pushed
the
clang-dev
branch
2 times, most recently
from
July 12, 2026 20:04
13da555 to
46bfe2e
Compare
Configure the target triple and -mcpu for Xtensa LLVM builds: - Resolve XTENSA_TOOLCHAIN_TARGET from CONFIG_SOC_TOOLCHAIN_NAME or the XTENSA_TOOLCHAIN_TARGET environment variable. - Map SDK toolchain target names to upstream LLVM -mcpu names via a small table (intel_ace15_mtpm -> intel_ace15_adsp, etc.). - Set triple to xtensa-<target>_zephyr-elf, select LLD linker and llvm bintools, and configure CROSS_COMPILE_TARGET accordingly. - Append core Clang flags: -mcpu, -D__XCC__, -D__XCC_CLANG__, -fintegrated-as, -gdwarf-4. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…ld for Xtensa For Xtensa LLVM builds, override compiler_set_linker_properties() to link against LLVM's compiler-rt builtins (libclang_rt.builtins) instead of libgcc. The compiler-rt builtins ship with the LLVM toolchain and cover all Xtensa intrinsics needed by Zephyr and SOF. Also derive the per-core SDK linker binary (XTENSA_SDK_LD) from XTENSA_TOOLCHAIN_TARGET so that tgl, ace15, ace30 and future cores each use their matching SDK ld binary rather than a hardcoded ace15 path. Configure CMAKE_REQUIRED_FLAGS, CMAKE_EXE_LINKER_FLAGS and CMAKE_ASM_FLAGS for the Xtensa compile-test and assembly steps. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…verrides Configure linker execution templates: - Use CMAKE_C_COMPILER and CMAKE_CXX_COMPILER directly as linker drivers, unless an external XTENSA_GCC compiler override is set. - Cleans up formatting and whitespace inside the LLD target macros. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
… default When building Zephyr with Clang/LLVM for Xtensa, ld.bfd cannot natively ingest LLVM-generated objects. Disable the forced -fuse-ld=bfd flag in cmake/linker/ld/target.cmake so LLD is used instead. Also disable FLIX VLIW bundling in the LLVM toolchain target when CONFIG_COMPILER_CODEGEN_VLIW_DISABLED is set. The LLVM FLIX packetizer generates invalid instruction pairs because the hardware slot constraints are not yet fully modelled; FLIX can be re-enabled per-build by adding '-Xclang -target-feature -Xclang +flix' to CMAKE_C_FLAGS. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…for ARM Configure LLEXT compilation options and stripping flags for ARM architectures: - Add LLEXT compiler options (LLEXT_REMOVE_FLAGS / LLEXT_APPEND_FLAGS) to cmake/compiler/clang/target_arm.cmake for Clang ARM builds. - Configure add_llext_target to strip .ARM.exidx* and .ARM.extab* exception handling and unwind table sections from the relocatable LLEXT module ELF file. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Configure CMAKE_C/CXX_CREATE_SHARED_LIBRARY and _MODULE to use the
llext-link-wrapper.sh script for Xtensa LLVM LLEXT shared-library
builds. The wrapper addresses two LLD issues:
1. Xtensa LLD rejects relocations into read-only sections (.rodata,
_log_const, .module, .exported_sym) with 'dangerous relocation in
read-only section'. The wrapper uses objcopy to mark those sections
writable before linking.
2. l32r literals must appear before their use in .text. The default
section order places .rodata after .text, violating this constraint.
The wrapper links with -mtext-section-literals so literals are
interleaved with code, and strips the X flag from .rodata afterwards
to prevent llext_link_helper.py from misclassifying it as executable.
Pass -fuse-ld=lld so the GCC wrapper driver uses LLD for the final link.
Disable ccache for link steps as it cannot cache the wrapper output.
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
When building LLEXT shared libraries with Clang/LLD two problems arise: 1. The Xtensa LLD linker rejects relocations into read-only sections (.rodata, _log_const, .module, .exported_sym) with "dangerous relocation in read-only section". Worked around by making those sections writable via objcopy before linking. 2. l32r literals must appear before their use in the .text section. The default section order places .rodata after .text, violating this. A linker script overlay (llext_shared.ld) places .rodata before .text and merges all .literal.* into .text. Add llext-link-wrapper.sh to orchestrate: mark sections writable, link with GCC -mtext-section-literals + linker script, then strip the X flag from .rodata in the output so llext_link_helper.py does not misclassify it as executable. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
When building with Clang/LLVM, all l32r literal loads must be within +/-512 KB of the instruction that references them. With large Xtensa images the literals placed in a separate .literal section by the GAS default can exceed this range, causing link-time relocation errors. -mtext-section-literals instructs the compiler to interleave literal pools with code in the .text section, guaranteeing they are always within l32r reach regardless of image size. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Under native LLVM builds the HAL module dir is keyed by CONFIG_SOC_TOOLCHAIN_NAME (e.g. intel_ace30_ptl), which can differ from CONFIG_SOC. Replace the single fixed include path with a two-pass existence check that appends CONFIG_SOC_TOOLCHAIN_NAME first and then CONFIG_SOC, so both naming conventions are supported without requiring every board to align them. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…sition for IAS Clang's Integrated Assembler (IAS) does not support the Xtensa GAS pseudo-op form 'rsr.epsN'/'rsr.epcN'; it requires the canonical two- operand form 'rsr <dst>, epsN'. Replace all occurrences in xtensa_asm2.inc.S. Also add '.literal_position' immediately after the '.text' directive in crt1.S to satisfy IAS requirements for literal pool placement at the start of the text section. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Cadence-generated core-isa.h headers for some SoCs (NXP, MediaTek) contain '#error xcc should not use this header' when __XCC__ is defined. This guard was intended to prevent Xtensa's proprietary XCC compiler from using the generic fallback header instead of the SoC-specific one, but it also blocks our LLVM Clang when we define __XCC__ to enable the HiFi intrinsic paths in SOF. Add a thin wrapper at arch/xtensa/include/xtensa/config/core-isa.h that: - When both __XCC__ and __XCC_CLANG__ are defined (LLVM Clang path), temporarily undefines __XCC__ before including_next, then restores it. - Otherwise falls through to include_next unconditionally. This allows Clang to traverse the SoC-specific core-isa.h without tripping the guard while retaining __XCC__ visibility everywhere else. Also fix xtensa_init_page_tables() in ptables.c: the 'entry' variable is used to store page table entries (32-bit values) but was declared as 'volatile uint8_t'. Change to uint32_t to match the actual use and silence Clang's -Wconversion warning. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Clang's Integrated Assembler (IAS) differs from GAS in two ways that require source changes: 1. Long conditional branches: IAS does not automatically relax conditional branches with offsets that exceed the instruction's range (unlike GAS which relaxes them silently). In userspace.S, replace the long 'bgeu' targeting a distant label with a short 'bltu' over an unconditional 'j' to stay within range. 2. Literal pool placement: IAS has no default strategy for placing Xtensa literal pools in hand-written assembly; it throws 'literal pool empty' errors unless explicitly directed. Wrap reset_vector.S with '.begin auto-litpools' / '.end auto-litpools' under Clang so IAS inserts literal pool boundaries automatically. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
… for LLD
LLD rejects absolute location counter assignments ('.\ = 0xYYY') in
generated linker scripts when the section VMA does not match. Rewrite
the Xtensa vector-offset assignments in gen_vectors.py to be relative
to the z_xtensa_vecbase symbol ('.\ = z_xtensa_vecbase + 0xYYY') so
LLD resolves them correctly at link time.
Note: the HAL include directory was already updated to prefer
CONFIG_SOC_TOOLCHAIN_NAME in a prior commit.
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Clang's Windowed ABI codegen stores the thread switch_handle at a different offset within the thread struct than GCC expects in the assembly context switch path. - xtensa_asm2_util.S: add the ___thread_t_switch_handle_OFFSET to a3 before storing a1 so the saved stack pointer lands in switch_handle rather than at the base of the thread struct. - kernel/include/kswap.h: pass the thread pointer directly to arch_switch() as the switch_from argument under CONFIG_XTENSA (the assembly side derives switch_handle via the offset above). Other architectures continue to pass &old_thread->switch_handle. Also add compiler barriers to prevent Clang from eliding the old/new thread pointer loads across the asm boundary. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
When building with LLVM clang, several SOF source files (copier_dai.c, channel_map.c) and Zephyr core (bitarray.c) emit calls to __popcountsi2. The precompiled libgcc.a version places its literal pool in a separate .literal section; on large Xtensa images (>~700 KB text) the l32r relocation from the code to that section exceeds the ±512 KB l32r range, causing a fatal link error. Add a popcount.c to the xtensa/core library, which is already compiled with -mtext-section-literals (see CMakeLists.txt). Text-section literals are interleaved with code, guaranteeing they are always within l32r reach. This definition is linked before libgcc is searched, so the problematic libgcc object is never pulled in. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…addr=0 For relocatable ELFs (ET_REL), all loadable sections have sh_addr=0 because no base address is assigned at link time. The previous code went directly to the sect_map path, which returns the runtime DRAM address. However this misses the bounds check and the pre-located ROM/IMR section case. Fix: - Add an explicit sh_ndx bounds check before accessing sect_hdrs. - For sections with sh_addr >= 0x08000000 (pre-located ROM/IMR), return llext_peek() at the section file offset. - ET_REL sections (sh_addr=0) fall through to the sect_map path which returns the correct DRAM address loaded by llext_map_sections(). Without this fix, on Intel ACE30 (PTL) where LLEXT is loaded from IMR, R_XTENSA_32 relocations receive a raw IMR file offset instead of the runtime DRAM address, causing ExcVaddr faults (seen as win0[0]=0x01009B01, win0[1]=0x001D003C on PTL/ACE30). Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…ions
In llext_link_plt(), the relocation target address for relocatable ELFs
(ET_REL) was computed as:
rel_addr = ext->mem[LLEXT_MEM_TEXT] - sects[LLEXT_MEM_TEXT].sh_offset
+ rela.r_offset + tgt->sh_offset
This arithmetic uses the file offset of the target section rather than
its runtime load address, producing a wrong relocation target when the
LLEXT is loaded from IMR into DRAM.
Fix: when 'tgt' is set (relocatable ELF path), compute the section
index from the section header pointer and call llext_loaded_sect_ptr()
to obtain the correct runtime address, then add rela.r_offset directly.
The shared/dynamic ELF path is unchanged.
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…r ET_REL Two fixes in llext_load.c for relocatable ELF (ET_REL) support: 1. llext_copy_symbols(): split the ET_REL and non-ET_REL code paths. For ET_REL, resolve the symbol address directly via llext_loaded_sect_ptr() + st_value; the previous code mixed both paths with a conditional subtraction of section_addr that produced wrong results for relocatable objects. 2. llext_map_sections(): the REGIONS_OVERLAP_ON() check on sh_offset is only meaningful for shared ELFs where sections have distinct file offsets. ET_REL sections all start at offset 0 (relative addressing), so the overlap check always fires and aborts loading. Guard it with 'ldr->hdr.e_type != ET_REL'. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Two fixes in arch/xtensa/core/elf.c for Xtensa LLEXT relocation: 1. arch_elf_relocate_local(): the existing code only handled the STT_SECTION case for non-ET_REL ELFs. For ET_REL, symbol addresses must be resolved through llext_loaded_sect_ptr() using the symbol's st_shndx, since sh_addr=0 for all sections. Add an ET_REL branch that computes sh_addr = loaded_section_base + sym->st_value. 2. xtensa_elf_relocate() / R_XTENSA_SLOT0_OP: global symbols (STB_GLOBAL) already have their final runtime address in the 'addr' argument passed by the generic LLEXT relocation engine; use it directly instead of reading the symbol table entry again. Local symbols continue to go through the symbol table path with llext_loaded_sect_ptr(). Also handle SHN_UNDEF and out-of-range st_shndx gracefully by setting sec_addr to 0 in the local-symbol path. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Initialize CPENABLE in _start before any C code runs so that all coprocessor units are enabled from the first instruction fetch. Without this, Clang-generated code that uses coprocessor registers (FPU, HiFi) before the Zephyr kernel enables them causes an illegal-instruction exception at boot. When CONFIG_XTENSA_LAZY_HIFI_SHARING is enabled only the non-AudioEngine coprocessors are enabled here; the AudioEngine CP is managed by the lazy sharing framework. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…dler LLVM auto-vectorizes C code using HiFi4 ae_* instructions (coprocessor CP1) throughout the exception handler (xtensa_excint1_c, print_fatal_ exception, and LOG calls). If CPENABLE doesn't have CP1 set when an exception fires — for example on a secondary CPU core before its CPENABLE is initialized, or after a context switch cleared it — the first HiFi4 ae_* instruction causes EXCCAUSE_CP_DISABLED(1) (exccause=29) as a double exception. This escalates to a triple fault, producing the 0xdb1e001d status visible in HP-SRAM window0. A runtime wsr.cpenable inside xtensa_excint1_c() itself is insufficient because LLVM places HiFi4 instructions in the function prologue before the first C statement executes. Fix: add movi+wsr.cpenable+rsync in pure assembly just before the callx4 into the C handler in the CROSS_STACK_CALL macro in xtensa_asm2.inc.S. At this point we are still in safe scalar assembly with no HiFi register usage, so the wsr.cpenable reliably fires before any C code runs. Guard with XCHAL_HAVE_CP to keep configurations without coprocessors unchanged. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…ption Root cause analysis of the 0xdb1e001d triple fault on ACE15/ARL-S: 1. CONFIG_XTENSA_LAZY_HIFI_SHARING clears the HiFi4 AudioEngineLX CP bit from CPENABLE on every thread context switch (xtensa_asm2_util.S:317). 2. LLVM generates HiFi4 ae_* instructions (ae_slaa32, ae_mulf32r etc.) in print_fatal_exception and its LOG/printk callees when compiling for the xtensa-intel_ace15_mtpm target. This happens at all optimisation levels, including -O0, as the Xtensa backend uses HiFi4 for scalar arithmetic on this core. 3. When the exception handler reaches print_fatal_exception with the HiFi4 CP bit cleared, the first ae_* instruction triggers EXCCAUSE_CP_DISABLED. Since PS.EXCM is set in the exception handler, this becomes a double exception -> triple fault, writing 0xdb1e001d to HP-SRAM window0. The CROSS_STACK_CALL assembly fix (wsr.cpenable before callx4) helps for fresh exceptions, but if the scheduler ran lazy HiFi sharing between the original fault and print_fatal_exception being reached, CPENABLE may be cleared again by an intermediate code path. Fix: explicitly set CPENABLE to all-ones immediately before the call to print_fatal_exception in xtensa_excint1_c. Use XCHAL_CP_NUM to compute the correct bitmask for this core (all CP bits enabled) rather than hardcoding 0xFF. Guard with XCHAL_HAVE_CP to keep pure-scalar cores clean. Also: retain wsr.cpenable in CROSS_STACK_CALL as defense-in-depth and revert the debug EPC1/DEPC breadcrumb changes to their original state. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
The existing xchal_cp1_load/store GAS macros in xtensa_hifi.S cannot be assembled by LLVM clang for intel_tgl_adsp: the tie-asm.h included by the cavs2.5 SDK uses an older macro form (RG-2017.8) whose xchal_sa_start / xchal_sa_align pseudo-ops are not recognised by the LLVM integrated assembler. Every instruction after them cascades as an unknown mnemonic. Provide a separate HiFi3 code path (guarded by CONFIG_XTENSA_CPU_HAS_HIFI3) that uses explicit ae_s64.i / ae_l64.i for aed0-aed15 and rur/wur for the six scalar AE state registers (AE_OVF_SAR, AE_BITHEAD, AE_TS_FTS_BU_BP, AE_CW_SD_NO, AE_CBEGIN0, AE_CEND0). The u0-u3 alignment scratch registers (ae_salign64.i / ae_lalign64.i) are omitted: LLVM-compiled SOF code uses only aligned ae_s64.i / ae_l64.i, so u0-u3 never carry live state across a context switch. Additionally, ae_lalign64.i and ae_salign64.i are FLIX bundles whose 8-byte encodings are absent from the clang TGL encoder table, so skipping them avoids a further assembler issue. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Clang auto-vectorizes the inner loops in memcpy() and memset() using Xtensa SIMD (BB, BBQ) instructions. These are not available on all Xtensa cores that SOF targets and produce an illegal-instruction exception when executed on cores without the vector engine. Add '#pragma clang loop vectorize(disable)' before each loop in memcpy() and memset() to prevent auto-vectorization. This has no effect on GCC builds. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…atable Configure section flags for the ADSP boot entry points: - In both IMR and primary ADSP boot.c inline assembly, change the section attribute declaration flags from "x" (executable) to "ax" (allocatable + executable). - Unlike GCC/GAS where the assembler automatically infers allocatable status for code sections, Clang/IAS does not automatically apply SHF_ALLOC to executable sections. If the boot section is not allocatable, the target linker excludes it from final memory image generation, failing to boot. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
… notes Configure Intel ADSP linker scripts for LLVM/LLD compatibility: - Replaces generic SEGSTART_CACHED/SEGSTART_UNCACHED macros with symbol-explicit ADDR_CACHED(sym)/ADDR_UNCACHED(sym) mapping macros. - Separates literal (*.literal, *.literal.*) and text (*.text, *.text.*) section wildcards to ensure LLD groups literals consistently ahead of text sections, preserving Xtensa L32R reach requirements. - Explicitly discards stack executability notes (*.note.GNU-stack) generated by Clang to prevent orphan section compiler warnings on older target linkers. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Configure the IMR boot loader stack mapping in the MMU page table: - In both mmu_ace30.c and mmu_ace40.c, add the XTENSA_MMU_MAP_SHARED attribute to the IMR boot stack region mapping. - This maps the boot stack in Ring 3 (shared ASID 4) instead of Ring 0 (ASID 1). - This ensures that register window exception handlers (which execute spills/fills using s32e/l32e with Ring 1 privilege) can successfully match the TLB entries for the stack, resolving early boot LoadStoreTLBMiss exceptions and preventing triple faults when the L2 page table page is not mapped in the TLB. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
- Provide the 'soc_cpus_active' array even when CONFIG_MP_MAX_NUM_CPUS == 1 to fix undefined reference errors during linking.
- Explicitly add .literal matching for .imr regions on Intel platforms. - Remove remaining '(!ari)' attributes from NXP i.MX linker scripts.
LLVM organizes sections differently from GCC, sometimes placing initialization code or structures into the Bootloader Isolated Memory Regions (IMR). Without these mappings, LLVM-compiled firmware triggers MMU faults (Instruction Fetch or Load/Store exceptions) during early boot. This patch adds explicit XTENSA_MMU_PERM_X and XTENSA_MMU_PERM_W mappings for IMR_BOOT_LDR_LIT_BASE, IMR_BOOT_LDR_TEXT_BASE, and IMR_BOOT_LDR_DATA_BASE on ACE30 and ACE40 SOCs.
The commit c3c8402 ('soc: intel_adsp: Configure cached/uncached mappings and discard stack notes') replaced generic SEGSTART_CACHED/SEGSTART_UNCACHED macros with ADDR_CACHED(sym)/ADDR_UNCACHED(sym) mapping macros. However, it used the static 'z_mapped_end' or '__bss_end' symbols instead of mapping the current location counter '.' after moving it to the end of SRAM. Under LLD (and under specific alignment configurations), this resets the location counter back to the end of the firmware image, resulting in a heap size of 0. When heap allocation occurs, subtracting the shared buffer size underflows, causing memory corruption (allocations overlap with the code segment). Fix this by mapping the current location counter '.' to cached/uncached memory when defining the heap end, heap sentry, and image RAM end markers. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
debug_window.c: lazily initialize the ADSP debug window on first use. When the debug window descriptor array starts with 0xffffffff (uncleared by the ROM), clear the entire window before any slot is allocated. This prevents stale ROM data from being misinterpreted as valid slot headers on cold boot. soc_util.h (bmemcpy/bbzero): use 32-bit word-aligned copies in the boot loader memory routines instead of byte-at-a-time loops. Clang strict aliasing analysis rejects the previous uint8_t pointer casts on aligned buffers, and the word copy is faster for the large IMR-to-DRAM firmware image copies performed at boot. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…register The GPDMA ownership register is a 16-bit MMIO register. Using sys_write32() triggers a load/store width exception under LLVM strict alignment checking. Replace with sys_write16() to match the actual register width. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Replace arch_num_cpus() with CONFIG_MP_MAX_NUM_CPUS in dw_ace_irq_enable and dw_ace_irq_disable loops. On platforms with CONFIG_SOC_HAS_RUNTIME_NUM_CPUS=y, arch_num_cpus() evaluates to the dynamic global variable soc_num_cpus. When compiling this loop with GCC 14.3.0 for Xtensa, the compiler generates a buggy loop trip count calculation that evaluates to 0 iterations at runtime. Consequently, Designware interrupts (such as Host IPC and HDA/DMA) are never enabled. Using the static compile-time constant CONFIG_MP_MAX_NUM_CPUS (5) prevents the compiler bug, enabling interrupts to be correctly delivered.
Select XTENSA_CPU_HAS_HIFI3 for the CAVS 2.5 (TGL) SOC series so that the XTENSA_HIFI_SHARING infrastructure knows the coprocessor is present. Without this the HiFi AE register file is never saved/restored across context switches, corrupting the state of any thread that uses HiFi instructions. Also fix the heap sentry calculation in the linker script: the L2 SRAM boundary was not being applied to the uncached address alias, placing _heap_sentry in the wrong region for the cavs2.5 memory map. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
… of CONFIG_MP_MAX_NUM_CPUS Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…r LLD Configure linker region layout macros for simulator builds: - In xtensa-dc233c.ld, replace generic location-counter-relative macros (SEGSTART_CACHED/SEGSTART_UNCACHED) with symbol-explicit region mapping macros (ADDR_CACHED/ADDR_UNCACHED). - Under LLVM/LLD, assigning different memory alias addresses using the location counter '.' triggers section overlap or counter inconsistency warnings. Explicitly mapping section addresses via symbols avoids this linking constraint. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
- Remove '(!ari)' custom memory region attributes, which are GNU ld specific and crash LLD. - Explicitly place .literal sections alongside .text across Intel, AMD, NXP, and Cadence DSP linkers. - Ensure correct placement of .struct and .symtab internal sections.
On Intel ADSP targets there is frequently no usable console or mtrace output when the firmware takes a fatal exception very early or inside a crash loop, which makes the faulting PC effectively invisible. The host SOF driver, however, prints HP-SRAM window0[0] as "Firmware state" and window0[1] as "status/error code" on an IPC timeout. Add CONFIG_XTENSA_ADSP_FATAL_BREADCRUMB (default n, depends on SOC_FAMILY_INTEL_ADSP) which, when enabled, records the faulting PC, exception cause, faulting virtual address and the faulting instruction word into window0 via its uncached alias from xtensa_excint1_c(). Only the first fatal exception is latched so the original fault survives a crash loop, and window0[3] counts exceptions. Query the window0 base address and uncached region via Device Tree macros (HP_SRAM_WIN0_BASE and CONFIG_INTEL_ADSP_UNCACHED_REGION) to prevent using hardcoded magic pointers. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
When a double exception escalates to a triple fault (escaping the CPU), record the EPC1, double-exception EXCCAUSE, and DEPC into HP-SRAM window0 via its uncached alias. This is a lightweight tracing aid that can be enabled in production builds to diagnose fatal CPU locks and double faults. Add CONFIG_XTENSA_ADSP_TRIPLE_FAULT_BREADCRUMB (default y, depends on SOC_FAMILY_INTEL_ADSP) to govern this feature independently of general fatal exception breadcrumbs. Construct the window0 uncached base address and the 0xdb1e0000 marker via bit shifts and additions in assembly rather than movi/l32r literals, to ensure LLVM IAS emits no out-of-range l32r relocations in the triple-fault handler (where literals pools may be unreachable). Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Add a Kconfig choice (XTENSA_ADSP_FATAL_BREADCRUMB_DATA) to select which diagnostic information is written to window0[1] (which is printed in dmesg as the 'status/error code' on IPC timeout): - Exception cause (default) - Faulting virtual address (excvaddr) - Caller return address (a0) Also fix compilation under Clang by: - Including <adsp_memory.h> in vector_handlers.c to define L2_SRAM_BASE. - Constructing the uncached memory window base (0x40024000/0x5e024000) and signature dynamically using bit shifts and additions in assembly (xtensa_asm2_util.S) to avoid literal generation under Clang's Integrated Assembler. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
The breadcrumb code in xtensa_excint1_c() reads the faulting instruction word via: win0[4] = *(volatile uint32_t *)(bsa->pc & ~3) This is unsafe when the exception was caused by a bad function pointer or corrupted GOT entry — in that case bsa->pc itself is unmapped, so dereferencing it triggers a double exception inside the exception handler producing the 0xdb1e001d triple fault signature. Guard the read with a range check against the DSP SRAM window [0xa0000000, 0xa2000000). PCs outside this range are skipped; win0[0] already contains the faulting PC so no diagnostic information is lost. This makes the breadcrumb infrastructure safe on both ACE15 (no MMU, bad PC silently accesses wrong memory) and ACE30 (MMU, bad PC faults). Fixes: 98cafd9 (xtensa: adsp: record fatal exception breadcrumbs in HP-SRAM window0) Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…0] < 0xa0000000 Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
… if TRIPLE_FAULT_BREADCRUMB is enabled Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…teral_position for IAS" This reverts commit 264b8f5. The modern upstream LLVM/Clang toolchain (version 23.0.0git) natively supports compiling the rsr.epsN/rsr.epcN instruction forms using the integrated assembler (-fintegrated-as). Additionally, .literal_position is not required for crt1.S compilation under the current toolchain. Testing confirms that removing this commit introduces no compilation failures for tgl, mtl, or ptl SOF targets. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Still very much early WIP that requires more testing and development but Zephyr and SOF now booting on qemu ACE 30 simulator and ztests passing. Will stay draft atm, but a heads up for any other xtensa users interested in llvm clang.
This PR does need more effort, but end result could be that Zephyr SDK only requires 1 xtensa compiler as clang can support different xtensa configs on the command line.
This work currently uses GNU binutils for assembly and linking as binutils is already fully ISA configured for each xtensa target based on the Cadence GPL overlay patches, i.e. its ready to go for testing a working front end. Subsequent work can help complete llvm linker/assembler support so that binutils no longer required.
This uses the LLVM patches here: llvm/llvm-project@main...lgirdwood:llvm-project:upstream/dev
@cgturner1 fyi - I will try and keep this ticking along, but its best effort atm.